package edu.buaa.act.helper;

import java.util.Arrays;
import java.util.Properties;



/**
 * Created by song on 2017/6/11 0011.
 */
public class Arguments extends Properties
{
    public enum Values {
        /**
         *  INPUT VALUES
         */
        // global configuration
        Parallel_Count("程序运行线程数", "how many threads will this task use", 20),
        Raw_Traj_Data_File("原始轨迹数据路径", "path to the raw trajectory data", "C:/tmp/trajectory.txt"),
        MapMatching_Map_Data_Path("OSM地图数据(pbf格式)路径", "path to map data used in mapMatching", "D:/beijing_osm.pbf"),
        Filter_Geo_Bound("全数据集经纬度Filter", "longitude and latitude filter (minLat, maxLat, minLon, maxLon) on whole data set", new double[]{39.6797, 40.2523, 116.0074, 116.7380}),//south,north,west,east

        // task specific config
        MapMatching_GPS_Accuracy("GPS最大误差(MapMatching)", "value feed to com.graphhopper.matching.MapMatching.setMeasurementErrorSigma() in mapMatching", 50),// relative with GPS sample rate.

        Filter_Start_Time("全数据集开始时间Filter", "trajectories whose start time is after this filter are ignored", "2016-03-05 00:00:00", "trajectory is removed from data set if it can not cover the time interval defined by this filter."),
        Filter_End_Time("全数据集结束时间Filter", "trajectories whose end time is before this filter are ignored", "2016-03-30 00:00:00", "is used together with Filter_Start_Time"),

        Test_Data_Count("测试集轨迹条数", "number of trajectories used as test set", 3),
        Test_Data_Filter_Start_Time("测试集开始时间", "GPS points before this time in test set are ignored", "2016-03-29 00:00:00", "usually 'start' from the beginning of the day"),
        Test_Data_Filter_End_Time("测试集结束时间", "GPS points after this time in the test set are ignored", "2016-03-29 23:59:59", "usually you should keep (end - start)>=1 day"),
        Test_Data_L2S_Time_Interval("测试集长轨迹to短轨迹时间间隔大小(毫秒)", "long trajectory in test data are cut into short ones (L2S) if time interval between two neighbor points are larger than this time", 20_000, "in milliseconds. only useful when Separate_Real_With_Time_Window is false"),

        Anonymity_Interpolation_Time_Interval("匿名插值间隔(毫秒)", "time interval between two GPS points in the data of the NWA input format transformed from raw data", 5_000, "in milliseconds"),
        Anonymity_Level_K("匿名程度K", "anonymous level K in K-d anonymous algorithm.", 2),
        Anonymity_NWA_EXE_Path("Never Walk Along项目可执行文件路径", "path to the 'nwa.exe'", "D:/nwa.exe"),
        Anonymity_L2S_Time_Window_Size("匿名后长轨迹to短轨迹的时间窗口大小(毫秒)", "long trajectory in anonymized cut into short ones (L2S): time window size", 20_000, "in milliseconds"),
        Anonymity_L2S_Time_Window_Start_Threshold("匿名后长轨迹to短轨迹时开启时间窗口的速度阈值(m/s)", "L2S: time window start if speed is lower than this value", 1),
        Anonymity_L2S_Time_Window_End_Threshold("匿名后长轨迹to短轨迹时结束时间窗口的速度变化阈值(m/s)", "L2S: time window close if speed change larger than this value", 1),

        Test_With_Anonymous_Data("使用匿名后的数据进行测试", "all data (sample & test) are anonymous", true, "set to 'false' means only training data is anonymous"),
        Anonymous_Separately("测试集和训练集分开进行匿名", "do anonymity on test data and training data separately", false, "set to 'false' means anonymous on all data then sample. Only valid when Test_With_Anonymous_Data is true"),
        Separate_Real_With_Time_Window("使用时间窗口方法将测试集长轨迹变短轨迹","Test data set L2S using time window method", false, "should set true when data set is not special car, only useful when Test_With_Anonymous_Data is false"),

        /**
         *  OUTPOUT VALUES
         */
        // simple statistics
        Train_Data_History_Road_Count("训练集历史数据中有车过的道路个数","number of roads passed by at least one car in training data in history", 110_000),
        Train_Data_History_Traj_Count("训练集历史数据中短轨迹总数","number of short trajectories in training data in history", 289653, "not include those failed in MapMatching process"),
        Train_Data_History_Total_Length("训练集历史数据中短轨迹总长度(米)","total length of short trajectories in training data in history", 1254965412.3, "in meters"),
        Train_Data_History_Total_Time("训练集历史数据中短轨迹总时间(秒)","total time of short trajectories in training data in history", 1879546215, "in seconds"),

        Train_Data_Recent_Road_Count("训练集近期数据中有车过的道路个数","number of roads passed by at least one car in training data in recent time", 10_000, "'recent' mean the time is between Test_Data_Filter_Start_Time and query time"),
        Train_Data_Recent_Traj_Count("训练集近期数据中短轨迹总数","number of short trajectories in training data in recent time", 23242, "not include those failed in MapMatching process"),
        Train_Data_Recent_Total_Length("训练集近期数据中短轨迹总长度(米)","total length of short trajectories in training data in recent time", 795642.1, "in meters"),
        Train_Data_Recent_Total_Time("训练集近期数据中短轨迹总时间(秒)","total time of short trajectories in training data in recent time", 135765, "in seconds"),

        Train_Data_MM_IN_OUT_RATIO("训练集数据MM成功率","output traj count/input traj count of training data in map matching", 0.8),
        Train_Data_Direct_Length("训练集短轨迹未MM的总长度", "total direct length of short trajs in training data", 1000, "the 'direct' length of a traj is the sum of the distance of its neighbored GPS points"),

        Test_Data_Total_Length("测试集中短轨迹总长度(米)","total length of short trajectories in test data", 79814, "in meters"),
        Test_Data_Total_Time("测试集中短轨迹总时间(秒)", "total time of short trajectories in test data", 6541, "in seconds"),
        Test_Data_Traj_Count("测试集中短轨迹总数","number of short trajectories in test data", 230, "not include those failed in map matching process"),
        Test_Data_MM_IN_OUT_RATIO("测试集数据MM成功率", "output traj count/input traj count of test data in map matching", 0.6),
        Test_Data_Direct_Length("测试集短轨迹未MM的总长度", "total direct length of short trajs in test data", 100),

        // aggregate values
        Train_Traj_AVG_Length("训练集短轨迹平均长度(米)", "average length of short trajectories in training data",2604, "in meters"),
        Train_Traj_AVG_Time("训练集短轨迹平均时间(秒)", "average time of short trajectories in training data",369, "in seconds"),
        Test_Traj_AVG_Length("测试集短轨迹平均长度(米)", "average length of short trajectories in test data",2488, "in meters"),
        Test_Traj_AVG_Time("测试集短轨迹平均时间(秒)", "average time of short trajectories in test data", 413, "in seconds"),
        Mean_Absolute_Error("绝对误差均值(分钟每轨迹)", "MAE = sum of error / number of trajectories",1.4, "in minutes (NOT seconds!) per trajectory"),
        Mean_Relative_Error("相对误差均值", "MRE = sum of error / some of truth", 0.3), // ratio
        MAE_Per_Kilometer("每公里绝对误差均值(分钟每公里)", "MAEL = sum of error / Test_Data_Total_Length", 0.145, "minutes per kilometer")

        ;

        public int id;
        String comment;
        String enComment;
        Object exampleVal;
        String description="-";

        Values(String descriptionChinese, String descriptionEnglish, Object exampleValue){
            this.comment = descriptionChinese;
            this.enComment = descriptionEnglish;
            this.exampleVal = exampleValue;
            this.id = Config.nextId();
        }

        Values(String descriptionChinese, String descriptionEnglish, Object exampleValue, String moreDescription){
            this.comment = descriptionChinese;
            this.enComment = descriptionEnglish;
            this.exampleVal = exampleValue;
            this.id = Config.nextId();
            this.description = moreDescription;
        }

        public String toString(boolean english){
            if(english){
                return enComment;
            }else{
                return comment;
            }
        }

        public String example(){
            return exampleVal.toString();
        }

        public String more(){
            return description;
        }
    }



    public static class Param
    {
        private Values name;
        private Object val;
        public Param(Values name, Object value){
            this.name = name;
            this.val = value;
        }
        public <T> T get(){
            return (T) val;
        }
        public void set(Object value){
            val = value;
        }
        public String toString(){
            return this.name+": "+this.val;
        }
        public String getStr(){
            if(val instanceof double[])
            {
                return Arrays.toString((double[]) val);
            }else{
                return this.val.toString();
            }
        }
    }
}
